feat: WritableStore PatchAsync (atomic batch writes)#50
Merged
Conversation
…ve layer merge Add PatchAsync to IWritableStore<T> for atomic batch overlay writes: any number of Set/SetSecret/Reset mutations apply under one read-merge-write — one backend write, one recompute — instead of one per property. A 20-field form save no longer fires 20 recomputes, and subscribers never observe a half-applied state. For a DB-backed IStoreBackend this collapses N round-trips into one. - IWritableStorePatch<T> builder: Set (value, incl. explicit null), SetSecret (pre-encrypted envelope), Reset. Presence-based semantics — present = set, absent = untouched, Reset = remove the override. - Sync + async (Func<.., Task>) overloads; the async one closes the async-void footgun and allows awaiting (e.g. secret encryption) inline. - Single-value SetAsync/SetSecretAsync/ResetAsync now delegate to PatchAsync. Fix: resetting a secret-typed member no longer throws (removing an override exposes no plaintext) — symmetry with SetSecretAsync. Internal cleanup (no public-API impact): pipeline layer merging is now case-insensitive on property names (Cocoar.Json.Mutable 1.2.0), consistent with how the effective config is read back (System.Text.Json case-insensitive, like IConfiguration). This removes the overlay's write-time base-casing alignment (Trap B): SparseOverlayMutator is reduced to thin MutableJsonPath glue (baseDom gone), and PatchAsync parses/serializes the overlay once per batch instead of once per property. Docs, changelog ([Unreleased]) and the WritableStoreExample updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
PatchAsynctoIWritableStore<T>— the one new feature: atomic batch overlay writes. Any number ofSet/SetSecret/Resetmutations apply under a single read-merge-write — one backend write, one recompute — instead of one per property. A 20-field form save no longer fires 20 recomputes, subscribers never observe a half-applied state, and for a DB-backedIStoreBackendit collapses N round-trips into one.API (new)
IWritableStore<T>.PatchAsync(Action<IWritableStorePatch<T>>, ct)+ asyncFunc<.., Task>overload (closes theasync voidfootgun, allows awaiting secret encryption inline).IWritableStorePatch<T>builder:Set(value incl. explicitnull),SetSecret(pre-encrypted envelope),Reset. Presence-based semantics — present = set, absent = untouched,Reset= remove the override (the only model that allows settingnullexplicitly and deleting an override).SetAsync/SetSecretAsync/ResetAsyncnow delegate toPatchAsync.Additive for callers (resolved via DI). → minor bump (5.2).
Fixed
NotSupportedException(removing an override exposes no plaintext) — symmetry withSetSecretAsync.Internal cleanup (no public-API impact)
IConfiguration).SparseOverlayMutatoris reduced to thinMutableJsonPathglue (baseDomgone), andPatchAsyncparses/serializes the overlay once per batch instead of once per property.Docs & tests
website/guide/providers/writable-store.md(Batch-writes section, presence semantics, secrets correction, form-save endpoint),changelog.md([Unreleased]),WritableStoreExample.🤖 Generated with Claude Code